package com.example.zookeeperlock.highlock.impl;

import com.example.zookeeperlock.highlock.AbstractLock;
import org.I0Itec.zkclient.IZkDataListener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @Author: zhangrongqing
 * @Date: 2020/9/1 11:29
 * 监听前一个节点，可以少做相关操作
 */
public class HighQualityLock extends AbstractLock {
    private String currentPath;

    private String beforePath;

    private CountDownLatch countDownLatch;

    public HighQualityLock() {
        try {
            //初始化根节点
            boolean exists = zkClient.exists(PATH);
            if (!exists) {
                zkClient.createPersistent(PATH);
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Boolean tryLock() {
        //创建本次节点
        if (null == currentPath) {
            currentPath = zkClient.createEphemeralSequential(PATH + "/", "lock");
        }

        //在之前创建了一个直接断currentPath，所以永远不为空
        List<String> children = zkClient.getChildren(PATH);
        Collections.sort(children);
//        System.out.println(children);
        if (currentPath.equals(PATH + "/" + children.get(0))) {
            return true;
        } else {
            //获取当前节点的前面一个节点
            int wz = Collections.binarySearch(children, currentPath.substring(PATH.length() + 1));
            beforePath = PATH + "/" + children.get(wz - 1);
            System.out.println(Thread.currentThread().getName() + " beforePath:" + beforePath);
        }

        return false;
    }

    @Override
    public void waitLock() {
        IZkDataListener iZkDataListener = new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            @Override
            public void handleDataDeleted(String s) throws Exception {
                System.out.println("检测到了节点失效");
                if(countDownLatch != null) {
                    countDownLatch.countDown();
                }
            }
        };

        System.out.println(Thread.currentThread().getName() + "监听前一个结点" + beforePath);
        zkClient.subscribeDataChanges(beforePath, iZkDataListener);

        if (zkClient.exists(beforePath)) {
            countDownLatch = new CountDownLatch(1);
            try {
                System.out.println(Thread.currentThread().getName() + "等待释放锁");
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


        System.out.println(Thread.currentThread().getName() + "运行到这");
        zkClient.unsubscribeDataChanges(beforePath, iZkDataListener);
    }

    @Override
    public void releaseLock() {
        System.out.println(Thread.currentThread().getName() + "释放锁：" + currentPath);
        zkClient.delete(currentPath);
        zkClient.close();
    }

}
